package com.roy.minimq.remoting.domain.netty;

import com.roy.minimq.remoting.domain.entity.NettyEvent;
import com.roy.minimq.remoting.domain.entity.common.ServiceThread;
import com.roy.minimq.remoting.service.ChannelEventListener;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

public class NettyEventExecutor extends ServiceThread {

    private final LinkedBlockingDeque<NettyEvent> eventQueue = new LinkedBlockingDeque<>();
    private final int maxSize = 10000;

    private ChannelEventListener channelEventListener;

    public NettyEventExecutor(ChannelEventListener channelEventListener) {
        this.channelEventListener = channelEventListener;
    }

    public void putNettyEvent(NettyEvent event){
        if (this.eventQueue.size() <= maxSize) {
            this.eventQueue.add(event);
        } else {
            logger.warn("event queue size[{}] enough, so drop this event {}", this.eventQueue.size(), event.toString());
        }
    }

    @Override
    public String getServiceName() {
        return NettyEventExecutor.class.getSimpleName();
    }

    @Override
    public void run() {
        logger.info(this.getServiceName() + " service started");
        while (!this.isStoped()){
            try {
                NettyEvent event = this.eventQueue.poll(3000, TimeUnit.MILLISECONDS);
                if(null != event){
                    switch (event.getType()){
                        case IDLE:
                            channelEventListener.onChannelIdle(event.getRemoteAddr(),event.getChannel());
                            break;
                        case CONNECT:
                            channelEventListener.onChannelConnect(event.getRemoteAddr(), event.getChannel());
                            break;
                        case CLOSE:
                            channelEventListener.onChannelClose(event.getRemoteAddr(), event.getChannel());
                            break;
                        case EXCEPTION:
                            channelEventListener.onChannelException(event.getRemoteAddr(), event.getChannel());
                            break;
                        default:
                            break;
                    }
                }
            } catch (InterruptedException e) {
                logger.warn(this.getServiceName() + " service has exception. ", e);
            }
        }
        logger.info(this.getServiceName() + " service stopped");
    }
}
